/**
 * Copyright (C) 2013 DaiKit.com - daikit-commons module (admin@daikit.com)
 *
 *         Project home : http://code.daikit.com/commons
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *         http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.daikit.commons.shared.utils;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;


/**
 * String utils that are usable with GWT
 * 
 * @author tcaselli
 * @version $Revision$ Last modifier: $Author$ Last commit: $Date$
 */
public abstract class DkStringUtils
{

	/**
	 * @param object
	 *           an Object
	 * @return given object as string or empty String if null
	 */
	public static String toString(final Object object)
	{
		return object == null ? "" : object.toString();
	}

	/**
	 * @param string
	 *           a String
	 * @return whether given string is (not null and not empty) or not
	 */
	public static final boolean hasText(final String string)
	{
		return string != null && !"".equals(string);
	}

	/**
	 * @param ch
	 *           a character
	 * @return whether the given character is a letter or not
	 */
	public static final boolean isLetter(final char ch)
	{
		return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z';
	}

	/**
	 * @param ch
	 *           a character
	 * @return whether the given character is a (letter or digit) or not
	 */
	public static final boolean isLetterOrDigit(final char ch)
	{
		return ch >= 'A' && ch <= 'Z' || ch >= 'a' && ch <= 'z' || ch >= '0' && ch <= '9';
	}

	/**
	 * @param tabNumber
	 * @param tabPattern
	 * @return a tab with indentation corresponding to given tab number
	 */
	public static final String getTab(final int tabNumber, final String tabPattern)
	{
		String tab = "";
		for (int i = 0; i < tabNumber; i++)
		{
			tab += tabPattern;
		}
		return tab;
	}

	/**
	 * Split at each positions of delimiters in given String
	 * 
	 * @param toSplit
	 * @param delimiter
	 * @return a split list of Strings
	 */
	public static final List<String> split(final String toSplit, final String delimiter)
	{
		final List<String> ret = new ArrayList<String>();
		if (toSplit != null)
		{
			final String[] temp = toSplit.split(delimiter);
			for (int i = 0; i < temp.length; i++)
			{
				ret.add(temp[i]);
			}
		}
		return ret;
	}

	/**
	 * Split at each indexes in given String
	 * 
	 * @param toSplit
	 * @param indexes
	 * @return a split list of Strings
	 */
	public static final List<String> splitAtIndexes(final String toSplit, final List<Integer> indexes)
	{
		final List<String> ret = new ArrayList<String>();
		final Iterator<Integer> it = indexes.iterator();
		int i = 0;
		int j = 0;
		while (it.hasNext())
		{
			j = it.next() + 1;
			if (j > toSplit.length())
			{
				break;
			}
			ret.add(toSplit.substring(i, j));
			i = j;
		}
		if (i < toSplit.length())
		{
			ret.add(toSplit.substring(i));
		}
		return ret;
	}

	/**
	 * Wrapper to {@link #collectionToString(Collection, String)} with separator = ", "
	 * 
	 * @param <X>
	 * @param collection
	 *           the collection to join
	 * @return a string representing the given collection joined with default separator ", "
	 */
	public static final <X> String collectionToString(final Collection<X> collection)
	{
		return collectionToString(collection, ", ");
	}

	/**
	 * Get the given collection as string with the given separator
	 * 
	 * @param <X>
	 * @param collection
	 *           the collection to join
	 * @param separator
	 *           the separator to join the collection with
	 * @return a string representing the given collection joined with given separator
	 */
	public static final <X> String collectionToString(final Collection<X> collection, final String separator)
	{
		String ret = "";
		final Iterator<X> it = collection.iterator();
		while (it.hasNext())
		{
			ret += it.next();
			if (it.hasNext())
			{
				ret += separator;
			}
		}
		return ret;
	}

	/**
	 * Join given String with " - "
	 * 
	 * @param objects
	 *           the objects to be joined
	 * @return the joined String
	 */
	public static String join(final Object... objects)
	{
		return joinsep(" - ", objects);
	}

	/**
	 * Join given String with " - "
	 * 
	 * @param collection
	 *           the {@link Collection} to be joined
	 * @return the joined String
	 */
	public static String join(final Collection<?> collection)
	{
		return joinsep(" - ", collection);
	}

	/**
	 * Join given Strings with given separator
	 * 
	 * @param separator
	 *           the separator
	 * @param objects
	 *           the Objects to be joined
	 * @return the joined String
	 */
	public static String joinsep(final String separator, final Object... objects)
	{
		return joinsep(separator, Arrays.asList(objects));
	}

	/**
	 * Join given Strings with given separator
	 * 
	 * @param separator
	 *           the separator
	 * @param collection
	 *           the {@link Collection} to be joined
	 * @return the joined String
	 */
	public static String joinsep(final String separator, final Collection<?> collection)
	{
		final StringBuilder sb = new StringBuilder(100);
		boolean first = true;
		for (final Object object : collection)
		{
			final String toString = toString(object);
			if (hasText(toString))
			{
				if (first)
				{
					first = false;
				}
				else
				{
					sb.append(separator);
				}
				sb.append(toString);
			}
		}
		return sb.toString();
	}

	/**
	 * Equivalent to {@link String#format(String, Object...)}
	 * 
	 * @param toFormat
	 *           the string to format that can contain %s as a placeholder for values to be replaced by arguments.
	 * @param arguments
	 *           the arguments to be replaced
	 * @return a formatted string
	 */
	public static String format(final String toFormat, final Object... arguments)
	{
		final String[] split = toFormat.split("%s");
		final StringBuffer buffer = new StringBuffer();
		for (int i = 0; i < split.length - 1; i++)
		{
			buffer.append(split[i]);
			buffer.append(arguments[i]);
		}
		buffer.append(split[split.length - 1]);
		return buffer.toString();
	}
}
